﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Xml;
using System.Xml.XPath;

namespace FTI.SP.LADM.EnhancedContentQueryWebPart.Exslt
{
    public sealed class ExsltDatesAndTimes
    {
        // Fields
        private static ExsltDatesAndTimes _Instance;

        // Methods
        private ExsltDatesAndTimes()
        {
        }

        public static string Add(string datetime, string duration)
        {
            try
            {
                DateTime time = DateTime.Parse(datetime, CultureInfo.CurrentCulture);
                TimeSpan span = XmlConvert.ToTimeSpan(duration);
                return XmlConvert.ToString(time.Add(span), XmlDateTimeSerializationMode.Local);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string AddDuration(string duration1, string duration2)
        {
            try
            {
                TimeSpan span = XmlConvert.ToTimeSpan(duration1);
                TimeSpan ts = XmlConvert.ToTimeSpan(duration2);
                return XmlConvert.ToString(span.Add(ts));
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string Avg(XPathNodeIterator iterator)
        {
            TimeSpan ts = new TimeSpan(0, 0, 0, 0);
            int count = iterator.Count;
            if (count == 0)
            {
                return string.Empty;
            }
            try
            {
                while (iterator.MoveNext())
                {
                    ts = XmlConvert.ToTimeSpan(iterator.Current.Value).Add(ts);
                }
            }
            catch (FormatException)
            {
                return string.Empty;
            }
            return Duration(ts.TotalSeconds / ((double)count));
        }

        public static string Date()
        {
            return DateTime.Now.ToString("s", CultureInfo.CurrentCulture).Split(new char[] { 'T' })[0];
        }

        public static string Date(string dateValue)
        {
            try
            {
                return DateTime.Parse(dateValue, CultureInfo.CurrentCulture).ToString("s", CultureInfo.CurrentCulture).Split(new char[] { 'T' })[0];
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string Datetime()
        {
            return DateTime.Now.ToString("s", CultureInfo.CurrentCulture);
        }

        public static string Datetime(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).ToString("s", CultureInfo.CurrentCulture);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string DayAbbreviation()
        {
            return DateTime.Now.DayOfWeek.ToString().Substring(0, 3);
        }

        public static string DayAbbreviation(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).DayOfWeek.ToString().Substring(0, 3);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static double DayInMonth()
        {
            return (double)DateTime.Now.Day;
        }

        public static double DayInMonth(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Day;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static double DayInWeek()
        {
            return (double)(DateTime.Now.DayOfWeek + 1);
        }

        public static double DayInWeek(string date)
        {
            try
            {
                return (double)(DateTime.Parse(date, CultureInfo.CurrentCulture).DayOfWeek + 1);
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static double DayInYear()
        {
            return (double)DateTime.Now.DayOfYear;
        }

        public static double DayInYear(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).DayOfYear;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static string DayName()
        {
            return DateTime.Now.DayOfWeek.ToString();
        }

        public static string DayName(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).DayOfWeek.ToString();
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static double DayOfWeekInMonth()
        {
            return DayOfWeekInMonth(DateTime.Now.Day);
        }

        private static double DayOfWeekInMonth(int day)
        {
            int num = 0;
            do
            {
                num++;
                day -= 7;
            }
            while (day > 0);
            return (double)num;
        }

        public static double DayOfWeekInMonth(string date)
        {
            try
            {
                return DayOfWeekInMonth(DateTime.Parse(date, CultureInfo.CurrentCulture).Day);
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static string Difference(string start, string end)
        {
            try
            {
                DateTime time = DateTime.Parse(start, CultureInfo.CurrentCulture);
                return XmlConvert.ToString(DateTime.Parse(end, CultureInfo.CurrentCulture).Subtract(time));
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string Duration(double seconds)
        {
            return XmlConvert.ToString(new TimeSpan(0, 0, (int)seconds));
        }

        public static string FormatDate(string date, string format)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).ToString(format, CultureInfo.CurrentCulture);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string FormatDate(string date, string format, string culture)
        {
            try
            {
                CultureInfo provider = new CultureInfo(culture);
                return DateTime.Parse(date, provider).ToString(format, provider);
            }
            catch
            {
                return string.Empty;
            }
        }

        public static double HourInDay()
        {
            return (double)DateTime.Now.Hour;
        }

        public static double HourInDay(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Hour;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        private static bool IsLeapYear(int year)
        {
            return CultureInfo.CurrentCulture.Calendar.IsLeapYear(year);
        }

        public static bool LeapYear()
        {
            return IsLeapYear(DateTime.Now.Year);
        }

        public static bool LeapYear(string date)
        {
            try
            {
                return IsLeapYear(DateTime.Parse(date, CultureInfo.CurrentCulture).Year);
            }
            catch (FormatException)
            {
                return false;
            }
        }

        public static string Max(XPathNodeIterator iterator)
        {
            TimeSpan span;
            if (iterator.Count == 0)
            {
                return string.Empty;
            }
            try
            {
                iterator.MoveNext();
                span = XmlConvert.ToTimeSpan(iterator.Current.Value);
                while (iterator.MoveNext())
                {
                    TimeSpan span2 = XmlConvert.ToTimeSpan(iterator.Current.Value);
                    span = (span2 > span) ? span2 : span;
                }
            }
            catch (FormatException)
            {
                return string.Empty;
            }
            return XmlConvert.ToString(span);
        }

        public static string Min(XPathNodeIterator iterator)
        {
            TimeSpan span;
            if (iterator.Count == 0)
            {
                return string.Empty;
            }
            try
            {
                iterator.MoveNext();
                span = XmlConvert.ToTimeSpan(iterator.Current.Value);
                while (iterator.MoveNext())
                {
                    TimeSpan span2 = XmlConvert.ToTimeSpan(iterator.Current.Value);
                    span = (span2 < span) ? span2 : span;
                }
            }
            catch (FormatException)
            {
                return string.Empty;
            }
            return XmlConvert.ToString(span);
        }

        public static double MinuteInHour()
        {
            return (double)DateTime.Now.Minute;
        }

        public static double MinuteInHour(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Minute;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static string MonthAbbreviation()
        {
            return DateTime.Now.ToString("m", CultureInfo.CurrentCulture).Split(new char[] { ' ' })[0].Substring(0, 3);
        }

        public static string MonthAbbreviation(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).ToString("m", CultureInfo.CurrentCulture).Split(new char[] { ' ' })[0].Substring(0, 3);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static double MonthInYear()
        {
            return (double)DateTime.Now.Month;
        }

        public static double MonthInYear(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Month;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static string MonthName()
        {
            return DateTime.Now.ToString("m", CultureInfo.CurrentCulture).Split(new char[] { ' ' })[0];
        }

        public static string MonthName(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).ToString("m", CultureInfo.CurrentCulture).Split(new char[] { ' ' })[0];
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static string ParseDate(string date, string format)
        {
            try
            {
                return XmlConvert.ToString(DateTime.Parse(date, CultureInfo.CurrentCulture), format);
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static double SecondInMinute()
        {
            return (double)DateTime.Now.Second;
        }

        public static double SecondInMinute(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Second;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static double Seconds()
        {
            try
            {
                DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0, 0, CultureInfo.CurrentCulture.Calendar);
                return DateTime.Now.Subtract(time).TotalSeconds;
            }
            catch
            {
                return double.NaN;
            }
        }

        public static double Seconds(string datetime)
        {
            double totalSeconds;
            try
            {
                DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0, 0, CultureInfo.CurrentCulture.Calendar);
                totalSeconds = DateTime.Parse(datetime, CultureInfo.CurrentCulture).Subtract(time).TotalSeconds;
            }
            catch (FormatException)
            {
                try
                {
                    return XmlConvert.ToTimeSpan(datetime).TotalSeconds;
                }
                catch (FormatException)
                {
                    return double.NaN;
                }
            }
            return totalSeconds;           
        }

        public static string Sum(XPathNodeIterator iterator)
        {
            TimeSpan ts = new TimeSpan(0, 0, 0, 0);
            if (iterator.Count == 0)
            {
                return string.Empty;
            }
            try
            {
                while (iterator.MoveNext())
                {
                    ts = XmlConvert.ToTimeSpan(iterator.Current.Value).Add(ts);
                }
            }
            catch (FormatException)
            {
                return string.Empty;
            }
            return XmlConvert.ToString(ts);
        }

        public static string Time()
        {
            return DateTime.Now.ToString("s", CultureInfo.CurrentCulture).Split(new char[] { 'T' })[1];
        }

        public static string Time(string date)
        {
            try
            {
                return DateTime.Parse(date, CultureInfo.CurrentCulture).ToString("s", CultureInfo.CurrentCulture).Split(new char[] { 'T' })[1];
            }
            catch (FormatException)
            {
                return string.Empty;
            }
        }

        public static double WeekInYear()
        {
            return WeekInYear(DateTime.Now);
        }

        private static double WeekInYear(DateTime date)
        {
            return (double)CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule, CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek);
        }

        public static double WeekInYear(string date)
        {
            try
            {
                return WeekInYear(DateTime.Parse(date, CultureInfo.CurrentCulture));
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        public static double Year()
        {
            return (double)DateTime.Now.Year;
        }

        public static double Year(string date)
        {
            try
            {
                return (double)DateTime.Parse(date, CultureInfo.CurrentCulture).Year;
            }
            catch (FormatException)
            {
                return double.NaN;
            }
        }

        // Properties
        public static ExsltDatesAndTimes Instance
        {
            get
            {
                if (_Instance == null)
                {
                    _Instance = new ExsltDatesAndTimes();
                }
                return _Instance;
            }
        }

    }
}
